package com.inspur.edp.bef.builtincomponents.auth;

import com.inspur.edp.bef.api.BefRtBeanUtil;
import com.inspur.edp.bef.api.be.IBEContext;
import com.inspur.edp.bef.api.exceptions.BefFuncPermissionDeniedException;
import com.inspur.edp.bef.api.lcp.AuthInfo;
import com.inspur.edp.bef.core.be.CoreBEContext;
import com.inspur.edp.cef.api.ValueGetterConfig;
import com.inspur.edp.cef.api.authority.AuthorityInfo;
import com.inspur.edp.cef.spi.entity.IAuthFieldValue;
import com.inspur.edp.udt.entity.ISimpleUdtData;
import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.permission.api.data.runtime.datapermission.DataPermissionContext;
import io.iec.edp.caf.permission.api.manager.runtime.DataPermissionManager;
import io.iec.edp.caf.securityentry.api.common.AuthType;
import io.iec.edp.caf.securityentry.api.data.AuthFieldEntry;
import io.iec.edp.caf.securityentry.api.data.DataPermissionEntity;
import io.iec.edp.caf.securityentry.api.data.PermissionEntity;
import io.iec.edp.caf.securityentry.api.data.SecurityEntry;
import io.iec.edp.caf.securityentry.api.manager.SecurityEntryService;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.annotation.Priority;

//适用于Erp场景的权限控制, 从原有代码提取逻辑保持不变,兼容原有的权限控制逻辑
@Priority(100)
public class ErpStyleDataPermissionController implements
    com.inspur.edp.bef.spi.auth.DataPermissionController<ErpStyleDataPermissionCache> {

  @Override
  public String getName() {
    return "default";
  }

  @Override
  public ErpStyleDataPermissionCache buildCache() {
    return new ErpStyleDataPermissionCache();
  }

  @Override
  public boolean checkDataAuthority(String actionCode, IBEContext beContext,
      AuthInfo authInfo, ErpStyleDataPermissionCache cache) {
    List<AuthFieldEntry> fields = getAuthFieldEntryList(actionCode, authInfo, cache);
    if (fields == null || fields.isEmpty()) {
      return true;
    }
    ArrayList<DataPermissionContext> permissions = new ArrayList<DataPermissionContext>();

    List<String> values = new ArrayList<>();

    for (AuthFieldEntry field : fields) {
      String data = null;
      ValueGetterConfig valueGetterConfig = new ValueGetterConfig();
      valueGetterConfig.setAssociationValue(false);
      valueGetterConfig.setSingleValueUdt(true);
      Object tempVar = BefRtBeanUtil
          .getValueGetter()
          .getValue(beContext.getCurrentData(), field.getFieldId(), valueGetterConfig);
      IAuthFieldValue authFieldValue = (IAuthFieldValue) ((tempVar instanceof IAuthFieldValue)
          ? tempVar : null);
      if (tempVar != null && tempVar instanceof ISimpleUdtData) {
        ISimpleUdtData data1 = (ISimpleUdtData) tempVar;
        if (data1.getValue() != null && data1.getValue() instanceof IAuthFieldValue) {
          data = ((IAuthFieldValue) data1.getValue()).getValue();
        } else if (data1.getValue() == null) {
          data = null;
        } else {
          data = String.valueOf(data1.getValue());
        }
      } else if (authFieldValue == null) {
        data = String.valueOf(beContext.getCurrentData().getValue(field.getFieldId()));
      } else {
        data = authFieldValue.getValue();
      }
      if (data == null || data.equals("")) {
        continue;
      }
      values.add(data);
      DataPermissionContext context = new DataPermissionContext();
      context.setData(data);
      context.setAuthFieldId(field.getAuthFieldId());
      context.setAuthorizationId(field.getAuthObjId());
      context.setAuthOp(field.getAuthOpRelations().get(0).getOperationId());

      permissions.add(context);
    }
    if (permissions == null || permissions.size() == 0) {
      return true;
    }
    String[] array = new String[values.size()];
    values.toArray(array);
    if (hasDataAuthByCache(cache, beContext, actionCode, array)) {
      return true;
    }

    Boolean permissionRez = getDataPermissionManager().isHasDataPermission(permissions);
    if (permissionRez == true) {
      addDataAuthToCache(cache, beContext, actionCode, array);
    }
    return permissionRez;
  }

  private static List<AuthFieldEntry> getAuthFieldEntryList(String actionCode,AuthInfo authInfo,
      ErpStyleDataPermissionCache cache) {
    if (!cache.cachedState) {
      SecurityEntryService securityEntryService = SpringBeanUtils.getBean(SecurityEntryService.class);
      cache.authSecurityEntry = securityEntryService
          .getAuthSecurityEntry(createEntry(AuthType.Auth, authInfo));
      cache.cachedState = true;
    }
    SecurityEntry authSecurityEntry = cache.authSecurityEntry;

    if (authSecurityEntry == null) {
      return null;
    }
    return authSecurityEntry.getAuthFieldEntryListByAction(actionCode);
  }

  private static SecurityEntry createEntry(AuthType authType, AuthInfo authInfo) {
    SecurityEntry entry = new SecurityEntry();
    entry.setEx1(authInfo.getExtend1());
    entry.setEx2(authInfo.getExtend2());
    entry.setEx3(authInfo.getExtend3());
    entry.setEx4(authInfo.getExtend4());
    entry.setEx5(authInfo.getExtend5());
    entry.setExtType(authInfo.getExtType());
    entry.setAuthType(authType);
    return entry;
  }

  private static boolean hasDataAuthByCache(ErpStyleDataPermissionCache cache, IBEContext beContext,
      String actionCode, String[] values) {
    if (beContext instanceof CoreBEContext) {
      return cache.hasValues(actionCode, values);
    }
    return false;
  }

  private static void addDataAuthToCache(ErpStyleDataPermissionCache cache, IBEContext beContext,
      String actionCode, String[] array) {
    if (beContext instanceof CoreBEContext) {
      cache.addAuthorityInfos(actionCode, array);
    }
  }

  @Override
  public List<AuthorityInfo> getQueryAuthInfo(AuthInfo authInfo,
      ErpStyleDataPermissionCache cache) {
    SecurityEntry entry = createEntry(AuthType.Auth, authInfo);
    // 从缓存中获取PermissionEntity
    PermissionEntity permissionEntity = cache.getPermissionEntityByCache(entry,"Query");
    if(permissionEntity==null)
      return Collections.emptyList();

    if(permissionEntity.isActionEnable()==false) {
      throw new BefFuncPermissionDeniedException();
    }
    if (permissionEntity.getDataPermissionEntities() == null || permissionEntity
        .getDataPermissionEntities().isEmpty())
      return Collections.emptyList();
    List<AuthorityInfo> list = new ArrayList<>(permissionEntity.getDataPermissionEntities().size());
    for (DataPermissionEntity item:permissionEntity.getDataPermissionEntities()) {
      if(item.getDataPermissionQueryFilter()==null)
        continue;
      AuthorityInfo tempVar = new AuthorityInfo();
      tempVar.setFieldName(item.getFieldId());
      tempVar.setSourceFieldName(item.getDataPermissionQueryFilter().getDataAuthResultDefColumnName());
      tempVar.setAuthoritySql(item.getDataPermissionQueryFilter().getDataAuthResultFilter());
      list.add(tempVar);
    }
    return list;
  }

  private static volatile DataPermissionManager dataPermissionManager;

  static DataPermissionManager getDataPermissionManager() {
    if (dataPermissionManager == null) {
      dataPermissionManager = SpringBeanUtils.getBean(DataPermissionManager.class);
    }
    return dataPermissionManager;
  }
}
